//
// itertool - a polynormial and type-safe iterator framework in C++.
//
// Copyright (c) 2021-2025 Feng Cong
//
// Distributed under the MIT Software License
// See accompanying file LICENSE.txt or copy at
// https://opensource.org/licenses/MIT

#pragma once

#include <itertool/itertool_fwd.h>

#include <type_traits>

namespace itertool {

namespace detail {

template <typename T>
class RepeatIterable : public Iterable<T> {
  static_assert(std::is_copy_constructible<T>::value,
                "Repeat requires T (the ItemType) to be copy constructible");

 public:
  using ItemType = T;

  RepeatIterable(const T& value, int times) : value_(value), times_(times) {}

  bool HasNext() override {
    if (!IsFinite()) {
      return true;
    }
    return now_ < times_;
  }

  ItemType GetNow() override { return value_; }

  void Advance() override {
    if (IsFinite()) {
      ++now_;
    }
  }

  bool IsFinite() override { return times_ >= 0; }

  bool IsResetable() override { return true; }

  void Reset() override {
    if (IsFinite()) {
      now_ = 0;
    }
  }

  size_t LengthHint() override { return IsFinite() ? (times_ - now_) : 0; }

 private:
  const T value_;
  const int times_;
  int now_ = 0;
};

}  // namespace detail

template <typename T>
Iterator<T> Repeat(const T& val, int times = -1) {
  return MakeIterator<detail::RepeatIterable<T>>(val, times);
}

}  // namespace itertool
